package com.easylinkin.linkappapi.listener;

import com.alibaba.fastjson.JSONObject;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.deviceattributestatus.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.deviceattributestatus.service.DeviceAttributeStatusService;
import com.easylinkin.linkappapi.deviceunit.entity.DeviceUnit;
import com.easylinkin.linkappapi.deviceunit.service.DeviceUnitService;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.codec.SerializationCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @program: linkapp-group
 * @description: 设备属性消息推送
 * @author: chenkaixuan
 * @create: 2021-07-20 10:15
 */
@ServerEndpoint("/deviceAttributeStatusListener/{tenantId}/{userId}")
@Component
public class DeviceAttributeStatusListener extends Listener{
    @Value("${linkapp.openReceiving:true}")
    private Boolean openReceiving;
    private static final Logger LOGGER = LoggerFactory.getLogger(DeviceAttributeStatusListener.class);
    private static CopyOnWriteArraySet<DeviceAttributeStatusListener> webSocketSet = new CopyOnWriteArraySet<>();
    private static DeviceAttributeStatusService deviceAttributeStatusService;
    private static DeviceUnitService deviceUnitService;
    private static DeviceService deviceService;
    private DeviceAttributeStatus deviceAttributeStatus;
//    private static RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;
    public static String WS_DEVICEATTRIBUTESTATUS_LISTEN = "WS_DEVICEATTRIBUTESTATUS_LISTEN";
    private RTopic topic;

    @Override
    @OnOpen
    public void onOpen(Session session, @PathParam("tenantId") String tenantId, @PathParam("userId") String userId) {
        init(session, tenantId, userId);
        // 加入set中
        webSocketSet.add(this);
    }

    @Override
    @OnClose
    public void onClose() {
        LOGGER.info("通知关闭连接,用户id:{}", getUserId());
        // 从set中删除
        webSocketSet.remove(this);
    }

    @Override
    @OnMessage
    public void onMessage(String message, Session session) {
        LOGGER.info("收到通知会话消息,message:{},用户id:{}", message, this.getUserId());
        if(StringUtils.isEmpty(message)){
            return;
        }
        this.deviceAttributeStatus = JSONObject.parseObject(message, DeviceAttributeStatus.class);
        if(StringUtils.isEmpty(this.deviceAttributeStatus)){
            return;
        }
        String msg = message(this.deviceAttributeStatus, this.getTenantId());
        if(StringUtils.isEmpty(msg)){
            return;
        }
        this.sendMessage(msg);
    }

    private String message(DeviceAttributeStatus deviceAttributeStatus,String tenantId){
        if(StringUtils.isEmpty(deviceAttributeStatus) || StringUtils.isEmpty(tenantId) || StringUtils.isEmpty(deviceAttributeStatus.getDeviceCode())){
            return null;
        }
        if(StringUtils.isEmpty(deviceAttributeStatus.getVersion())){
            Device oneByDeviceCode = deviceService.findOneByDeviceCode(deviceAttributeStatus.getDeviceCode());
            if(StringUtils.isEmpty(oneByDeviceCode)){
                return null;
            }
            //获取版本号
            DeviceUnit deviceUnit = deviceUnitService.getById(oneByDeviceCode.getDeviceUnitId());
            if(deviceUnit == null){
                return null;
            }
            deviceAttributeStatus.setVersion(deviceUnit.getVersion());
        }
        deviceAttributeStatus.setTenantId(tenantId);
        List<DeviceAttributeStatus> deviceRealtimeDataBigScreen = deviceAttributeStatusService.getDeviceRealtimeDataBigScreen(deviceAttributeStatus);
        if(deviceRealtimeDataBigScreen == null || deviceRealtimeDataBigScreen.size()<=0){
            return  null;
        }
        String msg = JSONObject.toJSONString(deviceRealtimeDataBigScreen);
        return msg;
    }

    /**
     * 开启监听
     */
    @PostConstruct
    void openReceiving() {
        if (!openReceiving) {
            return;
        }
        topic = redisson.getTopic(WS_DEVICEATTRIBUTESTATUS_LISTEN, new SerializationCodec());
        LOGGER.info("监听ws成功：{}", topic);
        topic.addListener(Device.class, (charSequence, device) -> {
            send(device);
        });
    }

    public void sendNotice(Device device) {
//        redis 发广播
        try {
            topic.publish(device);
        } catch (Exception e) {
            LOGGER.error("sendNotice失败：", e);
        }


//        String key = WS_DEVICEATTRIBUTESTATUS_LISTEN + UUID.randomUUID();
//        redisUtil.set(key+ "_param", device, 15);
//        //        10毫秒过期
//        redisUtil.setExpiredMilliseconds(key, "", 10);
    }

    /***
     * 消息推送
     */
    public void send(Device device) {
        if(StringUtils.isEmpty(device) || StringUtils.isEmpty(device.getCode()) || StringUtils.isEmpty(device.getTenantId()) || StringUtils.isEmpty(device.getDeviceUnitId())){
            return;
        }
        //获取版本号
        DeviceUnit deviceUnit = deviceUnitService.getById(device.getDeviceUnitId());
        if(deviceUnit == null){
            return;
        }
        DeviceAttributeStatus deviceAttributeStatus = new DeviceAttributeStatus();
        deviceAttributeStatus.setTenantId(device.getTenantId());
        deviceAttributeStatus.setDeviceCode(device.getCode());
        deviceAttributeStatus.setVersion(deviceUnit.getVersion());
        for (DeviceAttributeStatusListener listener : webSocketSet) {
            if (listener.getTenantId() != null && listener.getTenantId().equals(deviceAttributeStatus.getTenantId())
                    && deviceAttributeStatus.getDeviceCode().equals(listener.deviceAttributeStatus.getDeviceCode())) {
                String message = message(deviceAttributeStatus, listener.getTenantId());
                if(!StringUtils.isEmpty(message)){
                    listener.sendMessage(message);
                }
            }
        }
    }

    @Resource
    public  void setDeviceAttributeStatusService(DeviceAttributeStatusService deviceAttributeStatusService) {
        DeviceAttributeStatusListener.deviceAttributeStatusService = deviceAttributeStatusService;
    }
//    @Resource
//    public  void setRedisUtil(RedisUtil redisUtil) {
//        DeviceAttributeStatusListener.redisUtil = redisUtil;
//    }
    @Resource
    public  void setDeviceUnitService(DeviceUnitService deviceUnitService) {
        DeviceAttributeStatusListener.deviceUnitService = deviceUnitService;
    }
    @Resource
    public  void setDeviceService(DeviceService deviceService) {
        DeviceAttributeStatusListener.deviceService = deviceService;
    }
}
